import tracker from "../utils/tracker";
import onload from "../utils/onload";
import getLastEvent from "../utils/get-last-event";
import getSelector from "../utils/get-selector";

function timing() {
  let FMP, LCP;

  if (PerformanceObserver) {
    // 增加一个性能条目的观察者
    new PerformanceObserver((entryList, observer) => {
      let perfEntries = entryList.getEntries();
      FMP = perfEntries[0];
      observer.disconnect(); // 不再观察了
    }).observe({ entryTypes: ["element"] }); // 观察页面中的有意义的元素,需要手动指定

    new PerformanceObserver((entryList, observer) => {
      let perfEntries = entryList.getEntries();
      LCP = perfEntries[0];
      observer.disconnect(); // 不再观察了
    }).observe({ entryTypes: ["largest-contentful-paint"] }); // 观察页面中的有意义的元素

    new PerformanceObserver((entryList, observer) => {
      let lastEvent = getLastEvent();
      let firstInput = entryList.getEntries()[0];
      console.log("FID", firstInput);
      if (firstInput) {
        // processingStart 开始处理的时间  startTime 开始点击的时间  差值就是处理的延迟
        let inputDelay = firstInput.processingStart - firstInput.startTime;
        let duration = firstInput.duration; // 处理的耗时
        if (inputDelay > 0 || duration > 0) {
          tracker.send({
            kind: "experience", // 用户体验指标
            type: "firstInputDelay", // 首次输入延迟
            inputDelay, // 延时的时间
            duration, // 处理的时间
            startTime: firstInput.startTime,
            selector: lastEvent
              ? getSelector(lastEvent.path || lastEvent.target)
              : "",
          });
        }
      }
      observer.disconnect(); // 不再观察了
    }).observe({ type: "first-input", buffered: true }); // 观察页面中的有意义的元素
  }

  onload(function () {
    setTimeout(() => {
      const {
        navigationStart, // 初始化页面，在同一个浏览器上下文中前一个页面 unload 的时间戳，如果没有前一个页面的 unload，则与 fetchStart 值相等
        redirectStart, // 开始重定向 - 第一个 HTTP 重定向发生的事件，有跳转且是同域的重定向，否则为 0
        redirectEnd, // 结束重定向 - 最后一个重定向完成的时间，否则为 0
        fetchStart, // 开始获取文档 - 浏览器准备好实用 http 请求获取文档的时间，这发生在检查缓存之前
        domainLookupStart, // 开始解析域名 - DNS 域名开始查询的事件，如果有本地的缓存或 keep-alive 则时间为 0
        domainLookupEnd, // 结束域名解析- DNS 域名结束查询的时间
        connectStart, // 	开始连接 - TCP 开始建立连接的时间，如果是持久连接，则与 fetchStart 值相等
        secureConnectionStart, // 加密连接 https 连接开始的时间，如果不是安全链接则为 0
        connectEnd, // 结束连接 - TCP 完成握手的时间，如果是持久连接则与 fetchStart 值相等
        requestStart, // 开始请求 - HTTP 请求读取真实文档开始的事件，包括从本地缓存读取
        requestEnd, // 结束请求 - HTTP 请求读取真实文档结束的事件，包括从本地缓存读取
        responseStart, // 响应开始 - 返回浏览器从服务器收到（或从本地缓存读取）第一个字节时的 Unix 毫秒时间戳
        responseEnd, // 响应结束- 返回浏览器从服务器收到（或从本地缓存读取，或从本地资源读取）最后一个字节时的 Unix 毫秒时间戳
        domLoading, // 开始解析 DOM
        domInteractive, // DOM 结构结束解析
        domContentLoadedEventStart, // DOMContentLoaded 事件开始
        domContentLoadedEventEnd, // DOMContentLoaded 事件结束
        domComplete, // DOM 和资源解析完毕
        loadEventStart, // 开始load回调函数
        loadEventEnd, // 结束 load 回调函数
      } = performance.timing;
      const experienceTimeParams = {
        kind: "experienceTime", // 用户体验时间
        type: "timing",
        redirectTime: redirectEnd - redirectStart, //重定向时间
        cacheTime: domainLookupStart - fetchStart, //缓存检查时间
        dnsTime: domainLookupEnd - domainLookupStart, // 域名解析时间，可观察域名解析服务是否正常
        tcpConnectTime: connectEnd - connectStart, // TCP连接时间
        ttfbTime: responseStart - requestStart, // **首字节到达时间，发出页面请求到接收到应答数据第一个字节所花费的毫秒数**
        responseTime: responseEnd - responseStart, // 响应时间，观察网络是否正常
        domParseTime: domInteractive - domLoading, // 	DOM 解析耗时，观察 DOM 结构是否合理，是否有 JS 阻塞页面解析
        domContentLoadedTime:
          domContentLoadedEventEnd - domContentLoadedEventStart, // 当 HTML 文档被完全加载和解析完成后， DOM contentLoaded 事件被触发，无需等待样式表、图像和子框架的完成加载
        resourcesTime: domComplete - domContentLoadedEventEnd, // 资源加载耗时,可观察文档流是否过大
        blankScreenTime: responseEnd - fetchStart, // 首次渲染耗时,加载文档到看到第一帧非空图像的时间，也叫白屏时间
        timeToInteractive: domInteractive - fetchStart, // 首次可交互时间
        loadTime: loadEventStart - fetchStart, // 完整的加载时间
      };
      console.log("experienceTimeParams", experienceTimeParams);
      tracker.send(experienceTimeParams);

      let FP = performance.getEntriesByName("first-paint")[0];
      let FCP = performance.getEntriesByName("first-contentful-paint")[0];
      tracker.send({
        kind: "experienceKPI", // 用户体验指标
        type: "KPI",
        firstPaint: FP.startTime,
        firstContentfulPaint: FCP.startTime,
        firstMeaningfulPaint: FMP.startTime,
        largestContentfulPaint: LCP.startTime,
      });
    }, 3000);
  });
}

export default timing;
